<Serializable(), ObfuscationAttribute(Exclude:=True, ApplyToMembers:=True)> Friend Class Map

    Private m_address As Integer = 0
    Private m_width As Short = 0
    Private m_height As Short = 0
    Private m_trim As Short = 0
    Private m_byteSize As Byte = 1
    Private m_next As Map = Nothing
    Private m_description As String = ""
    <NonSerialized()> Private m_multiplier As Double = 1
    <NonSerialized()> Private m_mirrorable As Boolean = False

    Friend Sub New(ByVal Description As String)
        m_description = Description
    End Sub
    Friend Sub New(ByVal Address_ As Integer, ByVal width_ As Short, ByVal height_ As Short, ByVal description_ As String)
        m_address = Address_
        m_width = width_
        m_height = height_
        m_next = Nothing
        m_byteSize = 1
        m_description = Trim(description_)
    End Sub
    Friend Sub New(ByVal Address_ As Integer, ByVal width_ As Short, ByVal height_ As Short, ByVal description_ As String, ByVal ByteSize As Byte)
        m_address = Address_
        m_width = width_
        m_height = height_
        m_next = Nothing
        m_description = Trim(description_)
        m_byteSize = ByteSize
    End Sub
    Friend Sub New(ByVal Address_ As Integer, ByVal width_ As Short, ByVal height_ As Short, ByVal description_ As String, ByVal next_ As Map)
        m_address = Address_
        m_width = width_
        m_height = height_
        m_next = next_
        m_byteSize = 1
        m_description = Trim(description_)
    End Sub

    Friend Sub addNode(ByRef node As Map)
        If IsNothing(m_next) Then
            If node.getAddress() <> m_address Then
                m_next = node
            End If
        Else
            If node.getAddress() <> m_address Then
                m_next.addNode(node)
            End If
        End If
    End Sub
    Public Property Multiplier() As Double
        Get
            Return m_multiplier
        End Get
        Set(ByVal value As Double)
            m_multiplier = value
        End Set
    End Property
    Public Property Mirrorable() As Boolean
        Get
            Return m_mirrorable
        End Get
        Set(ByVal value As Boolean)
            m_mirrorable = value
        End Set
    End Property
    Friend Function lengthTotal() As Integer
        Dim intReturn As Integer
        intReturn = m_width * m_height * m_byteSize

        If (Not IsNothing(m_next)) Then
            intReturn = intReturn + m_next.lengthTotal
        End If

        Return (intReturn)
    End Function
    Friend ReadOnly Property Length() As Integer
        Get
            Return m_width * m_height * m_byteSize
        End Get
    End Property
    Friend Function compare(ByRef map1 As Map, ByRef map2 As Map) As Integer
        If Not IsNothing(map1) And Not IsNothing(map2) Then
            If map1.getWidth = map2.getWidth And map1.getHeight = map2.getHeight And map1.getByteSize = map2.getByteSize Then
                Return 0
            ElseIf map1.Length <= map2.Length Then
                Return -1
            Else
                Return 1
            End If
        End If
    End Function
    Shared Operator =(ByVal map1 As Map, ByVal map2 As Map) As Boolean
        If map1.getWidth = map2.getWidth And map1.getHeight = map2.getHeight And map1.getByteSize = map2.getByteSize Then
            Return True
        Else
            Return False
        End If
    End Operator
    Shared Operator <>(ByVal map1 As Map, ByVal map2 As Map) As Boolean
        If map1.getWidth = map2.getWidth And map1.getHeight = map2.getHeight And map1.getByteSize = map2.getByteSize Then
            Return False
        Else
            Return True
        End If
    End Operator

    Friend Function count() As Integer
        Dim intReturn As Integer = 1
        If (Not IsNothing(m_next)) Then
            intReturn += m_next.count
        End If
        Return (intReturn)
    End Function
    Friend Function getLength() As Integer
        Dim intReturn As Integer = m_width * m_height * m_byteSize
        Return (intReturn)
    End Function
    Friend Function getAddress() As Integer
        Return m_address
    End Function
    Friend Function getHeight() As Short
        Return m_height
    End Function
    Friend Function getWidth() As Short
        Return m_width
    End Function
    Friend Function getTrim() As Short
        Return m_trim
    End Function
    Friend Function getByteSize() As Byte
        Return m_byteSize
    End Function
    Friend Function getDescription() As String
        Return m_description
    End Function
    Friend Function getMultMap(ByRef Array_() As Byte) As Double()
        If m_multiplier <= 0 Then m_multiplier = 1
        Dim f_array() As Double = Nothing
        If m_byteSize = 1 And m_address <> 0 And UBound(Array_) >= (m_address + (m_width * m_height)) Then
            ReDim f_array(0 To ((m_width * m_height) - 1))
            For f_count As Integer = 0 To ((m_width * m_height * m_byteSize) - 1)
                f_array(f_count) = iByte(Array_(f_count + m_address) - m_trim) * m_multiplier
            Next
        ElseIf m_byteSize = 2 And m_address <> 0 And UBound(Array_) >= (m_address + (m_width * m_height * m_byteSize)) Then
            ReDim f_array(0 To ((m_width * m_height) - 1))
            For f_count As Integer = 0 To ((m_width * m_height * m_byteSize) - 1) Step m_byteSize
                f_array(f_count \ 2) = (iShort(MAKEWORD((Array_(f_count + m_address + 1)), (Array_(f_count + m_address)))) - m_trim) * m_multiplier
            Next
        End If
        Return f_array
    End Function
    Friend Function getMap(ByRef Array_() As Byte) As Byte()
        If m_multiplier = 0 Then m_multiplier = 1
        Dim f_array() As Byte = Nothing
        If m_address <> 0 And UBound(Array_) >= (m_address + (m_width * m_height)) Then
            ReDim f_array(0 To ((m_width * m_height * m_byteSize) - 1))
            For f_count As Integer = 0 To ((m_width * m_height * m_byteSize) - 1)
                f_array(f_count) = iByte(Array_(f_count + m_address) - m_trim)
            Next
        End If
        Return f_array
    End Function
    Friend Function getIntMap(ByRef Array_() As Byte) As Integer()
        If m_multiplier = 0 Then m_multiplier = 1
        Dim f_array() As Integer = Nothing
        If m_address <> 0 And UBound(Array_) >= (m_address + (m_width * m_height * m_byteSize)) And m_byteSize = 2 Then
            ReDim f_array(0 To ((m_width * m_height) - 1))
            For f_count As Integer = 0 To ((m_width * m_height * m_byteSize) - 2) Step 2
                f_array(f_count \ 2) = iShort(MAKEWORD((Array_(f_count + m_address + 1)), (Array_(f_count + m_address))) - m_trim)
            Next
        End If
        Return f_array
    End Function
    Friend Function getIntValue(ByRef array_() As Byte, ByVal Offset As Integer) As Integer
        If m_multiplier = 0 Then m_multiplier = 1
        Dim intReturn As Integer = 0
        If m_address <> 0 And UBound(array_) >= (m_address + (m_width * m_height * m_byteSize)) And m_byteSize = 2 Then
            intReturn = iShort(MAKEWORD((array_(m_address + (Offset * 2) + 1)), (array_(m_address + (Offset * 2)))) - m_trim)
        End If
        Return intReturn
    End Function
    Friend Function getValue(ByRef array_() As Byte, ByVal Offset As Integer) As Byte
        If m_multiplier = 0 Then m_multiplier = 1
        Dim byteReturn As Byte = 0
        If m_address <> 0 And UBound(array_) >= (m_address + (m_width * m_height)) And m_byteSize = 1 Then
            byteReturn = iByte(array_(m_address + (Offset)) - m_trim)
        End If
        Return byteReturn
    End Function

    Friend Sub setMap(ByRef toArray() As Byte, ByRef Grid As DataGridView)
        If m_multiplier = 0 Then m_multiplier = 1
    End Sub
    Friend Sub setByteSize(ByVal ByteSize As Byte)
        m_byteSize = ByteSize
    End Sub
    Friend Sub setMap(ByRef toArray_() As Byte, ByRef sourceArray_() As Byte)
        If m_multiplier = 0 Then m_multiplier = 1
        If m_address <> 0 And m_byteSize = 1 And (UBound(sourceArray_) - LBound(sourceArray_) + 1) = (m_width * m_height) And UBound(toArray_) >= (m_address + (m_width * m_height)) Then
            For f_count As Integer = 0 To ((m_width * m_height) - 1)
                toArray_(f_count + m_address) = iByte((sourceArray_(f_count)) + m_trim)
            Next
        ElseIf m_address <> 0 And m_byteSize = 2 And (UBound(sourceArray_) - LBound(sourceArray_) + 1) = (m_width * m_height * m_byteSize) And UBound(toArray_) >= (m_address + (m_width * m_height)) Then
            For f_count As Integer = 0 To ((m_width * m_height * m_byteSize) - 1)
                toArray_(f_count + m_address) = iByte((sourceArray_(f_count)) + m_trim)
            Next
        End If
    End Sub
    Friend Sub setMap(ByRef toArray_() As Byte, ByRef sourceArray_() As Integer)
        If m_multiplier = 0 Then m_multiplier = 1
        If m_address <> 0 And m_byteSize = 2 And (UBound(sourceArray_) - LBound(sourceArray_) + 1) = (m_width * m_height) And UBound(toArray_) >= (m_address + (m_width * m_height * m_byteSize)) Then
            For f_count As Integer = 0 To ((m_width * m_height) - 2)
                toArray_((f_count * 2) + m_address) = HIBYTE(iShort((sourceArray_(f_count)) + m_trim))
                toArray_((f_count * 2) + m_address + 1) = LOBYTE(iShort((sourceArray_(f_count)) + m_trim))
            Next
        End If
    End Sub
    Friend Sub setMap(ByRef toArray_() As Byte, ByRef sourceArray_() As Double)
        If m_multiplier = 0 Then m_multiplier = 1
        If m_address <> 0 And m_byteSize = 1 And (UBound(sourceArray_) - LBound(sourceArray_) + 1) = (m_width * m_height) And UBound(toArray_) >= (m_address + (m_width * m_height * m_byteSize)) Then
            For f_count As Integer = 0 To ((m_width * m_height) - 1)
                toArray_(f_count + m_address) = iByte((sourceArray_(f_count) / m_multiplier) + m_trim)
            Next
        ElseIf m_address <> 0 And m_byteSize = 2 And (UBound(sourceArray_) - LBound(sourceArray_) + 1) = (m_width * m_height) And UBound(toArray_) >= (m_address + (m_width * m_height * m_byteSize)) Then
            For f_count As Integer = 0 To ((m_width * m_height) - 2)
                toArray_((f_count * 2) + m_address) = HIBYTE(iShort((sourceArray_(f_count) / m_multiplier) + m_trim))
                toArray_((f_count * 2) + m_address + 1) = LOBYTE(iShort((sourceArray_(f_count) / m_multiplier) + m_trim))
            Next
        End If
    End Sub
    Friend Sub setValue(ByRef array_() As Byte, ByVal Offset As Integer, ByVal Value_ As Byte)
        If m_multiplier = 0 Then m_multiplier = 1
        If m_address <> 0 And m_byteSize = 1 And UBound(array_) >= (m_address + (m_width * m_height)) Then
            array_(m_address + Offset) = (Value_) + m_trim
        End If
    End Sub
    Friend Sub setAddress(ByVal address_ As Integer)
        m_address = address_
    End Sub
    Friend Sub setHeight(ByVal height_ As Short)
        m_height = height_
    End Sub
    Friend Sub setTrim(ByVal Trim_ As Short)
        m_trim = Trim_
    End Sub
    Friend Sub setWidth(ByVal Width_ As Short)
        m_width = Width_
    End Sub
    Friend Sub setDescription(ByVal Desc_ As String)
        m_description = Desc_
    End Sub

    Friend Sub setNext(ByRef nextNode_ As Map)
        m_next = nextNode_
    End Sub
    Friend Function getNext() As Map
        Return m_next
    End Function

    Protected Overrides Sub Finalize()
        MyBase.Finalize()
    End Sub
End Class